﻿using HDJ.Framework.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;

namespace HDJ.Framework.Core
{
    /// <summary>
    /// 从服务器上更新资源到沙河路径
    /// </summary>
   public  class UpdateAssetsManager:MonoBehaviour
    {
        public enum UpdateAssetsAction
        {
            /// <summary>
            /// 检查是否有更新
            /// </summary>
            CheckUpdate,
            /// <summary>
            /// 更新包
            /// </summary>
            UpdatePackage,
            /// <summary>
            /// 完成
            /// </summary>
            Complete,
        }
        /// <summary>
        /// 更新时动作回调<动作类型,总数,当前进行到的数目,错误说明>
        /// </summary>
        public static CallBack<UpdateAssetsAction,int,int,string> updateActionCallBack;

        private static MonoBehaviour monoBehaviour;
        private static string serverIP;
       
        public static void StartUpdate(string serverIP)
        {
            Debug.Log("StartUpdate serverIP :" + serverIP);
            UpdateAssetsManager.monoBehaviour = new GameObject("[UpdateAssetsManager]").AddComponent<UpdateAssetsManager>();
            UpdateAssetsManager.serverIP = serverIP;

            monoBehaviour.StartCoroutine( Init());
        }

        private static string platformFolderName = "";
        private static AssetBundleInfo localABInfo;
        private static string persistentAssetPath = "";
        private static IEnumerator Init()
        {
            platformFolderName = UnityExtendUtils.GetPlatformFolderName(Application.platform);
            persistentAssetPath = PathUtils.GetSpecialPath(platformFolderName + "/" , SpecialPathType.Persistent);
            string pathPer = persistentAssetPath + UpdateAssetsConst.AssetBundleInfoFileName;
            string pathSteam = PathUtils.GetSpecialPath(platformFolderName + "/" + UpdateAssetsConst.AssetBundleInfoFileName, SpecialPathType.StreamingAssets);

            pathSteam = UnityExtendUtils.GetWWWLoadPath(pathSteam);

            AssetBundleInfo streamABInfo = null;

            WWW www = new WWW(pathSteam);
            yield return www;
            Debug.Log("获取Stream下版本文件: " + www.text + "www.error : " + www.error);
            if ( !string.IsNullOrEmpty(www.error))
            {
                //网络不好
                Debug.LogError(www.error);
            }
            else
            {
                streamABInfo = JsonUtils.FromJson<AssetBundleInfo>(www.text);
                localABInfo = streamABInfo;
            }
            //如果沙河路径存在以前的更新，那么比较沙河路径版本与StreamingAssets下资源版本
            if (File.Exists(pathPer))
            {
                string ss = FileUtils.LoadTextFileByPath(pathPer);
                AssetBundleInfo perABInfo = JsonUtils.FromJson<AssetBundleInfo>(ss);
                int comper = OtherUtils.CompareVersions(perABInfo.gameVersion, streamABInfo.gameVersion);
                //游戏版本不同，删除沙盒路径的更新资源
                if (comper != 0)
                {
                    Directory.Delete(Path.GetDirectoryName(pathPer), true);
                    localABInfo = streamABInfo;
                }
                else
                {
                    //AB版本沙盒路径的小，删除更新
                    if (perABInfo.assetBundleVersion < streamABInfo.assetBundleVersion)
                    {
                        Directory.Delete(Path.GetDirectoryName(pathPer), true);
                        localABInfo = streamABInfo;
                    }
                    else
                    {
                        localABInfo = perABInfo;
                    }
                }
            }

            monoBehaviour.StartCoroutine(CheckCanUpdateAssets());
        }

        private static string serverFilePathDir;
        private static IEnumerator CheckCanUpdateAssets()
        {
            InvokUpdateActionCallBack(UpdateAssetsAction.CheckUpdate, 1, 1);

            serverFilePathDir = serverIP + "/" + localABInfo.gameName + "/" + platformFolderName +"/"+ localABInfo.gameVersion+"/";
            
            WWW www = new WWW(serverFilePathDir+ UpdateAssetsConst.VersionControlInfoFileName);
            yield return www;
            Debug.Log("获取服务器下更新包的版本文件: "+ UpdateAssetsConst.VersionControlInfoFileName+"  :" + www.text + "www.error : " + www.error+"\n"+ serverFilePathDir + UpdateAssetsConst.VersionControlInfoFileName);
            if (!string.IsNullOrEmpty(www.error))
            {
                InvokUpdateActionCallBack(UpdateAssetsAction.Complete, 1, 1, www.error);
                //网络不好
                Debug.LogError(www.error);
            }
            else
            {
                VersionControlInfo versionControl = JsonUtils.FromJson<VersionControlInfo>(www.text);

                versionControl.assetBundleVersions.Sort();
                //获得要更新的包的版本和生成路径
                List<string> updateVPath = new List<string>();
                foreach (var item in versionControl.assetBundleVersions)
                {
                    if(item > localABInfo.assetBundleVersion)
                    {
                        updateVPath.Add(serverFilePathDir + item + ".zip");
                    }
                }

                for (int i = 0; i < updateVPath.Count; i++)
                {
                    InvokUpdateActionCallBack(UpdateAssetsAction.UpdatePackage, updateVPath.Count, i+1);

                    yield return monoBehaviour.StartCoroutine(UpdatingAssets(updateVPath[i]));
                }
                if (updateVPath.Count == 0)
                {
                    Debug.Log("无需更新！");
                }
                InvokUpdateActionCallBack(UpdateAssetsAction.Complete, 1, 1);
            }
           
        }

        private static IEnumerator UpdatingAssets(string pakPath)
        {
            WWW www = new WWW(pakPath);
            yield return www;
            Debug.Log("获取服务器的更新包: " + pakPath + "www.error : " + www.error);
            if (!string.IsNullOrEmpty(www.error))
            {
                //网络不好
                Debug.LogError(www.error);
            }
            else
            {
                string savePath = PathUtils.GetSpecialPath(Path.GetFileName(pakPath), SpecialPathType.Persistent);
                //生成压缩包 如 Application.persistentDataPath + "/0.zip";
                Debug.Log("生成压缩包 : " + savePath);
                FileUtils.CreateFile(savePath, www.bytes);
                //解压到 Application.persistentDataPath + "/0/"
                ZipUtils.UnZip(savePath, "");

                //加载压缩包里的 PathFile.txt

                string dir = savePath.Replace(".zip","")+"/";

                Dictionary<string, string> pathUpdateDic = LoadPathData(dir  + UpdateAssetsConst.PathFileName);

                Dictionary<string, string> localPerDataPath = new Dictionary<string, string>();

                if(File.Exists(persistentAssetPath+ UpdateAssetsConst.PathFileName))
                {
                    localPerDataPath = LoadPathData(persistentAssetPath + UpdateAssetsConst.PathFileName);
                }

                foreach (var item in pathUpdateDic)
                {
                    if (localPerDataPath.ContainsKey(item.Key))
                    {
                        localPerDataPath[item.Key] = item.Value;
                    }
                    else
                    {
                        localPerDataPath.Add(item.Key, item.Value);
                    }

                    FileUtils.MoveFile(dir + Path.GetFileName(item.Value), persistentAssetPath + item.Value);
                }
                FileUtils.MoveFile(dir + UpdateAssetsConst.AssetBundleInfoFileName, persistentAssetPath + UpdateAssetsConst.AssetBundleInfoFileName);
                FileUtils.CreateTextFile(persistentAssetPath + UpdateAssetsConst.PathFileName, JsonUtils.ToJson(localPerDataPath));
                Directory.Delete(dir, true);
                FileUtils.DeleteFile(savePath);
            }
        }

        private static Dictionary<string,string> LoadPathData(string path)
        {
            string jsonU = FileUtils.LoadTextFileByPath(path);

           return JsonUtils.FromJson<Dictionary<string, string>>(jsonU);
        }
        private static void InvokUpdateActionCallBack(UpdateAssetsAction action,int count,int progess,string error=null)
        {
            if (updateActionCallBack != null)
                updateActionCallBack(action, count, progess, error);
        }
    }
}
